如果我們想實作從清單刪除日記的行為,首先就是要讓清單可以變動內容。
此系列文章是以我的業餘專案: Kimoji 作為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!
立馬下載 限免兌換碼
像是 ArrayList<T>
或 mutableListOf
這類可變動物件在這邊無法發揮效果。這些物件不會通知 Compose 清單項目有變,並為 UI 排定 recomposition。我們必須使用其他的 API。
我們需要建立 MutableList
的 instance,以便讓 Compose 觀察。這種資料結構可以讓 Compose 追蹤變更,以便在新增或移除清單項目時 recompose UI。
首先,定義可觀察的 MutableList
。我們可以從原本的 mutable 或 immutable Collection
,例如 List
,利用 toMutableStateList()
extension function 來建立可觀察的 MutableList
。
我們也可以使用 factory method mutableStateListOf
來建立可觀察的 MutableList
,然後加入 elements 來初始化這個 MutableList
。
mutableStateOf
函式會回傳MutableState<T>
類型的物件。
mutableStateListOf
和toMutableStateList
函式會回傳SnapshotStateList<T>
類型的物件。在文章中提到的:「可觀察的MutableList
」指的就是這個類別。
開啟 DiaryScreen.kt
檔案。把 getDiaries
函式移到這個檔案內,以便使用。先呼叫 getDiaries()
,然後使用我們剛提到的 toMutableStateList
extension function 建立清單。
import androidx.compose.runtime.remember
import androidx.compose.runtime.toMutableStateList
@Composable
fun DiaryScreen(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
StatefulCounter()
val diaries = remember { getDiaries().toMutableStateList() }
Journal(diaries = diaries, onDelete = { diary -> list.remove(diary) })
}
}
private fun getDiaries() = List(30) { i -> Diary(i, "Day # $i") }
注意:我們也可以改用
mutableStateListOf
API 建立清單。不過使用方式可能會導致非預期的 recomposition,並拖慢 UI 效能。如果我們只有定義 list,沒有初始化。然後在程式其他行把日記加到清單內,就會導致每一次 recomposition 都會加入重複的日記項目。
// Don't do this! val list = remember { mutableStateListOf<Diary>() } list.addAll(getDiaries())
要改用以單行指令建立清單,並給定初始值,然後再包到 remember 函式內,如下所示:
// Do this instead. val list = remember { mutableStateListOf<Diary>().apply { addAll(getDiaries()) } }
此系列文章是以我的業餘專案:Kimoji 為範例。
Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!
立馬下載 限免兌換碼
Reference: https://developer.android.com/codelabs/jetpack-compose-state